﻿#include "BaseAbilityTypes.h"

#include "BaseGameplayTags.h"

//重写 GameplayEffectContext 序列化函数
bool FBaseGameplayEffectContext::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
	uint32 RepBits = 0;
	//判断存档是否在保存
	if (Ar.IsSaving())
	{
		//检查是否复制发起者且发起者有效
		if (bReplicateInstigator && Instigator.IsValid())
		{
			RepBits |= 1 << 0;
		}
		//检查是否复制效果原因且效果原因有效
		if (bReplicateEffectCauser && EffectCauser.IsValid() )
		{
			RepBits |= 1 << 1;
		}
		//检查技能CDO是否有效
		if (AbilityCDO.IsValid())
		{
			RepBits |= 1 << 2;
		}
		//检查是否复制源对象且源对象有效
		if (bReplicateSourceObject && SourceObject.IsValid())
		{
			RepBits |= 1 << 3;
		}
		//检查是否有Actor数组
		if (Actors.Num() > 0)
		{
			RepBits |= 1 << 4;
		}
		//检查命中结果是否有效
		if (HitResult.IsValid())
		{
			RepBits |= 1 << 5;
		}
		//检查是否有世界原点
		if (bHasWorldOrigin)
		{
			RepBits |= 1 << 6;
		}
		//拓展是否格挡
		if (bIsBlockedHit)
		{
			RepBits |= 1 << 7;
		}
		//拓展是否闪避
		if (bIsDodgeHit)
		{
			RepBits |= 1 << 8;
		}
		//拓展是否吸收
		if (bIsAbsorbHit)
		{
			RepBits |= 1 << 9;
		}
		//拓展是否暴击
		if (bIsCriticalHit)
		{
			RepBits |= 1 << 10;
		}
		//伤害类型
		if (DamageType.IsValid())
		{
			RepBits |= 1 << 11;
		}
		//是否成功触发debuff
		if (bIsSuccessfulDebuff)
		{
			RepBits |= 1 << 12;
		}
		//异常伤害
		if (DebuffDamage > 0.f)
		{
			RepBits |= 1 << 13;
		}
		//异常持续时间
		if (DebuffDuration > 0.f)
		{
			RepBits |= 1 << 14;
		}
		//异常每跳频率
		if (DebuffFrequency > 0.f)
		{
			RepBits |= 1 << 15;
		}
		//击败敌人死亡时冲击向量
		if (!DeathImpulse.IsZero())
		{
			RepBits |= 1 << 16;
		}
		//击退方向向量
		if (!KnockbackForce.IsZero())
		{
			RepBits |= 1 << 17;
		}
		//拓展是否硬直
		if (bIsStagger)
		{
			RepBits |= 1 << 18;
		}
		//硬直值
		if (Stagger > 0.f)
		{
			RepBits |= 1 << 19;
		}
		//是否径向衰减伤害(也就是距离中心越远伤害越低)
		if (bIsRadialDamage)
		{
			RepBits |= 1 << 20;
			//径向内半径
			if (RadialDamageOuterRadius > 0.f)
			{
				RepBits |= 1 << 21;
			}
			//径向外半径
			if (RadialDamageInnerRadius > 0.f)
			{
				RepBits |= 1 << 22;
			}
			//径向起源点
			if (RadialDamageOrigin.IsZero())
			{
				RepBits |= 1 << 23;
			}
		}
		
		
	}
	Ar.SerializeBits(&RepBits, 19);

	if (RepBits & (1 << 0))
	{
		Ar << Instigator;
	}
	if (RepBits & (1 << 1))
	{
		Ar << EffectCauser;
	}
	if (RepBits & (1 << 2))
	{
		Ar << AbilityCDO;
	}
	if (RepBits & (1 << 3))
	{
		Ar << SourceObject;
	}
	if (RepBits & (1 << 4))
	{
		SafeNetSerializeTArray_Default<31>(Ar, Actors);
	}
	//检查命中结果是否有效
	if (RepBits & (1 << 5))
	{
		if (Ar.IsLoading())
		{
			if (!HitResult.IsValid())
			{
				//如果不存在就创建一个新的
				HitResult = TSharedPtr<FHitResult>(new FHitResult());
			}
		}
		HitResult->NetSerialize(Ar, Map, bOutSuccess);
	}
	if (RepBits & (1 << 6))
	{
		Ar << WorldOrigin;
		bHasWorldOrigin = true;
	}
	else
	{
		bHasWorldOrigin = false;
	}
	//拓展是否格挡
	if (RepBits & (1 << 7))
	{
		Ar << bIsBlockedHit;
	}
	//拓展是否格挡
	if (RepBits & (1 << 8))
	{
		Ar << bIsDodgeHit;
	}
	//拓展是否格挡
	if (RepBits & (1 << 9))
	{
		Ar << bIsAbsorbHit;
	}
	//拓展是否暴击
	if (RepBits & (1 << 10))
	{
		Ar << bIsCriticalHit;
	}
	//伤害类型
	if (RepBits & (1 << 11))
	{
		if (Ar.IsLoading())
		{
			if (!DamageType.IsValid())
			{
				//如果不存在就创建一个新的
				DamageType = TSharedPtr<FGameplayTag>(new FGameplayTag());
			}
		}
		DamageType->NetSerialize(Ar, Map, bOutSuccess);
	}
	//是否成功触发debuff
	if (RepBits & (1 << 12))
	{
		Ar << bIsSuccessfulDebuff;
	}
	//异常伤害
	if (RepBits & (1 << 13))
	{
		Ar << DebuffDamage;
	}
	//异常持续时间
	if (RepBits & (1 << 14))
	{
		Ar << DebuffDuration;
	}
	//异常每跳频率
	if (RepBits & (1 << 15))
	{
		Ar << DebuffFrequency;
	}
	//击败敌人死亡时冲击向量,向量自带网络序列化 所以不需要TSharedPtr 共享指针
	if (RepBits & (1 << 16))
	{
		DeathImpulse.NetSerialize(Ar, Map, bOutSuccess);
	}
	//击退方向向量
	if (RepBits & (1 << 17))
	{
		KnockbackForce.NetSerialize(Ar, Map, bOutSuccess);
	}
	//拓展是否硬直
	if (RepBits & (1 << 18))
	{
		Ar << bIsStagger;
	}
	//硬直值
	if (RepBits & (1 << 19))
	{
		Ar << Stagger;
	}
	//是否径向衰减伤害(也就是距离中心越远伤害越低)
	if (RepBits & (1 << 20))
	{
		Ar << bIsRadialDamage;
		//径向内半径
		if (RepBits & (1 << 21))
		{
			Ar << RadialDamageOuterRadius;
		}
		//径向外半径
		if (RepBits & (1 << 22))
		{
			Ar << RadialDamageInnerRadius;
		}
		//径向起源点
		if (RepBits & (1 << 23))
		{
			RadialDamageOrigin.NetSerialize(Ar, Map, bOutSuccess);
		}
	}
	
	if (Ar.IsLoading())
	{
		AddInstigator(Instigator.Get(), EffectCauser.Get()); // Just to initialize InstigatorAbilitySystemComponent
	}	
	
	bOutSuccess = true;
	return true;
}
